From e1e7aa6e073a62e565f12076ef485a6546c76a02 Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Fri, 17 Nov 2006 15:53:29 +0000 Subject: [PATCH] [XEND] Fix missing domains on domU reboot. Fixed regression with rebooting domU caused by the change in handling syncing state from Xen and Xend. Added missing implementation for XendDomainInfo.unwatchVm() which disappeared during a merge. Added protection for console/vnc-port reading for managed domains. Signed-off-by: Alastair Tse --- tools/python/xen/xend/XendConfig.py | 2 +- tools/python/xen/xend/XendDomain.py | 40 +++++++++++++++++-------- tools/python/xen/xend/XendDomainInfo.py | 20 +++++++++---- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 2d86122428..1b0c58d316 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -583,7 +583,7 @@ class XendConfig(dict): old_state = sxp.child_value(parsed, 'state') if old_state: for i in range(len(CONFIG_OLD_DOM_STATES)): - cfg[CONFIG_OLD_DOM_STATES[i]] = (old_state[i] != '-') + cfg[CONFIG_OLD_DOM_STATES[i]] = int(old_state[i] != '-') # Xen API extra cfgs # ------------------ diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 700f2609e1..79b5aec1a6 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -33,7 +33,7 @@ import xen.lowlevel.xc from xen.xend import XendRoot, XendCheckpoint, XendDomainInfo from xen.xend.PrettyPrint import prettyprint from xen.xend.XendConfig import XendConfig -from xen.xend.XendError import XendError, XendInvalidDomain +from xen.xend.XendError import XendError, XendInvalidDomain, VmError from xen.xend.XendLogging import log from xen.xend.XendConstants import XS_VMROOT from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_RUNNING @@ -65,7 +65,6 @@ class XendDomain: @type domains_lock: threaading.RLock @ivar _allow_new_domains: Flag to set that allows creating of new domains. @type _allow_new_domains: boolean - """ def __init__(self): @@ -281,9 +280,13 @@ class XendDomain: sxp_cache_file = open(self._managed_config_path(dom_uuid),'w') prettyprint(dominfo.sxpr(), sxp_cache_file, width = 78) sxp_cache_file.close() - except IOError: - log.error("Error occurred saving configuration file to %s" % - domain_config_dir) + except: + log.exception("Error occurred saving configuration file " + + "to %s" % domain_config_dir) + try: + self._managed_domain_remove(dom_uuid) + except: + pass raise XendError("Failed to save configuration file to: %s" % domain_config_dir) else: @@ -377,20 +380,34 @@ class XendDomain: # update information for all running domains # - like cpu_time, status, dying, etc. running = self._running_domains() - for dom in running: - domid = dom['domid'] - if domid in self.domains and dom['dying'] != 1: - self.domains[domid].update(dom) + running_domids = [d['domid'] for d in running if d['dying'] != 1] # remove domains that are not running from active domain list. # The list might have changed by now, because the update call may # cause new domains to be added, if the domain has rebooted. We get - # the list again. - running_domids = [d['domid'] for d in running if d['dying'] != 1] + # the list again. for domid, dom in self.domains.items(): if domid not in running_domids and domid != DOM0_ID: self._remove_domain(dom, domid) + # Add domains that are not already tracked but running in Xen, + # and update domain state for those that are running and tracked. + for dom in running: + domid = dom['domid'] + if domid in self.domains and dom['dying'] != 1: + self.domains[domid].update(dom) + elif domid not in self.domains and dom['dying'] != 1: + try: + new_dom = XendDomainInfo.recreate(dom, False) + self._add_domain(new_dom) + except VmError: + log.exception("Unable to recreate domain") + try: + xc.domain_destroy(domid) + except: + log.exception("Hard destruction of domain failed: %d" % + domid) + def _add_domain(self, info): """Add a domain to the list of running domains @@ -409,7 +426,6 @@ class XendDomain: @param info: XendDomainInfo of a domain to be removed. @type info: XendDomainInfo """ - if info: if domid == None: domid = info.getDomid() diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index ab3c79356d..7e91ac9bd0 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -403,7 +403,7 @@ class XendDomainInfo: self.vmWatch = None self.shutdownWatch = None self.shutdownStartTime = None - + self.state = DOM_STATE_HALTED self.state_updated = threading.Condition() self.refresh_shutdown_lock = threading.Condition() @@ -430,7 +430,7 @@ class XendDomainInfo: initialisation if it not started. """ from xen.xend import XendDomain - + if self.state == DOM_STATE_HALTED: try: self._constructDomain() @@ -443,7 +443,6 @@ class XendDomainInfo: # save running configuration if XendDomains believe domain is # persistent - # if is_managed: xendomains = XendDomain.instance() xendomains.managed_config_save(self) @@ -475,6 +474,9 @@ class XendDomainInfo: log.debug('XendDomainInfo.shutdown') if self.state in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,): raise XendError('Domain cannot be shutdown') + + if self.domid == 0: + raise XendError('Domain 0 cannot be shutdown') if not reason in DOMAIN_SHUTDOWN_REASONS.values(): raise XendError('Invalid reason: %s' % reason) @@ -920,7 +922,7 @@ class XendDomainInfo: # the VM path now, otherwise we will end up with one # watch for the old domain, and one for the new. self._unwatchVm() - elif reason in ['poweroff', 'reboot']: + elif reason in ('poweroff', 'reboot'): restart_reason = reason else: self.destroy() @@ -1521,6 +1523,14 @@ class XendDomainInfo: def _unwatchVm(self): """Remove the watch on the VM path, if any. Idempotent. Nothrow guarantee.""" + try: + try: + if self.vmWatch: + self.vmWatch.unwatch() + finally: + self.vmWatch = None + except: + log.exception("Unwatching VM path failed.") def testDeviceComplete(self): """ For Block IO migration safety we must ensure that @@ -1663,7 +1673,7 @@ class XendDomainInfo: result = self.info.get_sxp(domain = self, ignore_devices = ignore_store) - if not ignore_store: + if not ignore_store and self.dompath: vnc_port = self._readDom('console/vnc-port') if vnc_port is not None: result.append(['device', -- 2.30.2